/*
 * @FileName: 
 * @Version: 
 * @Author: 王杨洋
 * @Date: 2021-06-13 18:07:20
 */
/*
 * @FileName: 
 * @Version: 
 * @Author: 王杨洋
 * @Date: 2021-06-10 18:24:38
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include "../include/message.h"
#include "../include/device_manage.h"
#include "../include/media.h"
#define NAME_PASSWORD_LEN 128

// #define DEBUG
static int GetCurSeq(void)
{
	static int cur_seq = 0;
	cur_seq++;
	if(cur_seq >= 0xFF)
	{
		cur_seq = 0;
	}
	return cur_seq;
}

static int GetChkSum(char* data, int dataLen)
{
	int sum = 0;
	for(int i = 0; i < dataLen; i++)
	{
		sum += data[i];
	}
	return sum;
}

static void PrintMsg(MsgStruct *msg)
{
#ifdef DEBUG
	printf("Msg version:0x%x\n", msg->version);
	printf("Msg header_len:0x%x\n", msg->header_len);
	printf("Msg encrypt_type:0x%x\n", msg->encrypt_type);
	printf("Msg protocol_type:0x%x\n", msg->protocol_type);
	printf("Msg total_len:0x%x\n", msg->total_len);
	printf("Msg date_type:0x%x\n", msg->data_type);
	printf("Msg seq_num:0x%x\n", msg->seq_num);
	printf("Msg frag_flag:0x%x\n", msg->frag_flag);
	printf("Msg frag_offset:0x%x\n", msg->frag_offset);
	printf("Msg custom1:0x%x\n", msg->custom1);
	printf("Msg custom2:0x%x\n", msg->custom2);
	printf("Msg header_chk:0x%x\n", msg->header_chk);
	printf("Msg source_addr:0x%x\n", msg->source_addr);
	printf("Msg target_addr:0x%x\n", msg->target_addr);
	for(int i = 0; i < msg->total_len-msg->header_len; i++)
	{
		printf("Msg data[%d]:0x%x\n", i, msg->data[i]);
	}
#endif
}

void DoRegister(int sockfd, MsgStruct *msg)
{
	int preSeq = GetCurSeq();
	char name[NAME_PASSWORD_LEN] = {0};
	char password[NAME_PASSWORD_LEN] = {0};
	printf("Input name:\n(Tips: alphabet, number, underscore)\n");
	scanf("%s", name);
	getchar();

	printf("Input passwd:\n(Tips: alphabet, number, underscore)\n");
	scanf("%s", password);
	getchar();

	msg->version = MSG_VERSION;
	msg->header_len = MSG_HEADER_STABLE_LEN;
	msg->encrypt_type = MSG_ENCRYPT_NONE;
	msg->protocol_type = MSG_PROTOCOL_C2S;
	msg->data_type = MSG_DATA_ACCOUNT_REGISTER;
	msg->seq_num = preSeq;
	msg->frag_flag = MSG_FLAG_FRAG_NO;
	msg->frag_offset = 0;
	msg->custom1 = strlen(name);
	msg->custom2 = strlen(password);
	msg->total_len = MSG_HEADER_STABLE_LEN+msg->custom1+msg->custom2;
	msg->source_addr = 0x7F000001;//GetIpMun(sourceIp)
	msg->target_addr = 0x7F000001;//GetIpMun(targetIp)
	msg->header_chk = GetChkSum((char*)(msg), MSG_HEADER_STABLE_LEN);
	memcpy(msg->data, name, msg->custom1);
	memcpy(msg->data + 1 + msg->custom1, password, msg->custom2);

	if(send(sockfd, msg, sizeof(MsgStruct), 0) < 0)
	{
		perror("fail to send.\n");
		return;
	}
	memset(msg, 0x0, sizeof(MsgStruct));
	if(recv(sockfd, msg, sizeof(MsgStruct), 0) < 0)
	{
		perror("Fail to recv.\n");
		return;
	}
	
	PrintMsg(msg);
	//Check Some Param
	if(msg->version != MSG_VERSION)
	{
		printf("version error:0x%x.\n", msg->version);
		return;		
	}
	if(msg->encrypt_type != MSG_ENCRYPT_NONE)
	{
		printf("encrypt_type error:0x%x.\n", msg->encrypt_type);
		return;		
	}
	if(msg->protocol_type != MSG_PROTOCOL_S2C)
	{
		printf("protocol_type error:0x%x.\n", msg->protocol_type);
		return;		
	}
	if(msg->data_type != MSG_DATA_ACCOUNT_REGISTER)
	{
		printf("data_type error:0x%x.\n", msg->data_type);
		return;		
	}
	if(msg->frag_flag != MSG_FLAG_FRAG_NO)
	{
		printf("frag_flag error:0x%x.\n", msg->frag_flag);
		return;		
	}
	if(msg->seq_num != preSeq)
	{
		printf("seq error:0x%x; preSeq:0x%x.\n", msg->seq_num, preSeq);
		return;				
	}
	if(msg->header_chk != GetChkSum((char*)(msg), msg->header_len))
	{
		printf("header_chk error:0x%x.\n", msg->header_chk);
		return;		
	}

	//Get Result
	if(msg->custom1 == MSG_CUSTOM1_ACCOUNT_REG_SUCCESS)
	{
		printf("Congratulations！You registered successfully!\n");
	}
	else if(msg->custom1 == MSG_CUSTOM1_ACCOUNT_REG_FAILURE)
	{
		printf("Sorry！You registered failed:\n");
		switch (msg->custom2)
		{
			case MSG_CUSTOM2_ACCOUNT_REG_FAILURE_ALREADY:
				printf("Account already exist.\n");
				break;
			case MSG_CUSTOM2_ACCOUNT_REG_FAILURE_CONNECT:
				printf("Connection failed.\n");
				break;
			case MSG_CUSTOM2_ACCOUNT_REG_FAILURE_DATABASE:
				printf("Database error.\n");
				break;		
			default:
				printf("unknow reason:0x%x\n", msg->custom2);
				break;
		}
	}
	else
	{
		printf("Return unknow status:0x%x\n",msg->custom1);
	}

	return;
}

int main(int argc, const char *argv[])
{
	int deviceSockFd = -1;

	struct sockaddr_in serveraddr;
	int cmd;
	MsgStruct msg;
	memset(&msg, 0x0, sizeof(MsgStruct));

	char focusMac[32] = "01:11:22:33:44:55:66:77";;
	char para[128] = {0};
	const char sourceIp[32] = "127.0.0.1";

	//2.Connect Device Service
	if((deviceSockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("fail to socket.\n");
		return -1;
	}

	bzero(&serveraddr, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr(sourceIp);
	serveraddr.sin_port = htons(SERVER_DEVICE_PORT);

	if(connect(deviceSockFd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
	{
		perror("fail to connect");
		return -1;
	}

    printf("**************************AIRCONDITION***************************\n");
	printf("*       0.on  1.off  2.hot  3.cold  4.temperature  5.Wind       *\n");
	printf("*****************************************************************\n");
	printf("Please choose:");
	scanf("%d", &cmd);
	getchar();
	switch (cmd) {
		case 0:
		case 1:
		case 2:
		case 3:
			memset(&msg, 0x0, sizeof(MsgStruct));
			SendDeviceCommand(deviceSockFd, MSG_DATA_SET_DEVICE_STATUS, MSG_CUSTOM1_SET_DEVICE_AIRCONDITION, cmd, focusMac);//2、3、4、5为设备参数设置
            break;
		case 4:
		case 5:
			printf("Please input parameter:");
			scanf("%s", para);
			getchar();
			memset(&msg, 0x0, sizeof(MsgStruct));
			SendDeviceCommand(deviceSockFd, 0x04, 0, cmd, focusMac, para);
			break;
		default:
			break;
	}
	return 0;
}
